Instead of writing errors to
authoremellor@leeni.uk.xensource.com <emellor@leeni.uk.xensource.com>
Sun, 23 Oct 2005 21:34:13 +0000 (22:34 +0100)
committeremellor@leeni.uk.xensource.com <emellor@leeni.uk.xensource.com>
Sun, 23 Oct 2005 21:34:13 +0000 (22:34 +0100)
/local/domain/0/backend/<devclass>/<dom>/<devid>/error, write them instead to
/local/domain/0/error/backend/<yada>.  This is not the best place for them
perhaps, but it moves them out of the backend directory, on which the drivers
have a watch.  This fixes the problem whereby writing an error will trigger a
watch, causing the error message to be written again, and repeat.  Fixes bug
#286.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c
tools/examples/xen-backend.agent
tools/python/xen/util/diagnose.py

index efaffe2393b9cbee48f9f926258194b522293821..c8d1204fc244eb07bb38029024467dbb31ee8670 100644 (file)
@@ -516,17 +516,38 @@ int xenbus_printf(struct xenbus_transaction *t,
 }
 EXPORT_SYMBOL(xenbus_printf);
 
+/**
+ * Return the path to the error node for the given device, or NULL on failure.
+ * If the value returned is non-NULL, then it is the caller's to kfree.
+ */
+static char *error_path(struct xenbus_device *dev)
+{
+       char *path_buffer = kmalloc(strlen("error/") + strlen(dev->nodename) +
+                                   1, GFP_KERNEL);
+       if (path_buffer == NULL) {
+               return NULL;
+       }
+
+       strcpy(path_buffer, "error/");
+       strcpy(path_buffer + strlen("error/"), dev->nodename);
+
+       return path_buffer;
+}
+
 /* Report a (negative) errno into the store, with explanation. */
 void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...)
 {
        va_list ap;
        int ret;
        unsigned int len;
-       char *printf_buffer;
+       char *printf_buffer = NULL, *path_buffer = NULL;
 
        printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
-       if (printf_buffer == NULL)
+       if (printf_buffer == NULL) {
+               printk("xenbus: failed to write error node for %s (%d): %d\n",
+                      dev->nodename, err, errno);
                goto fail;
+       }
 
        len = sprintf(printf_buffer, "%i ", -err);
        va_start(ap, fmt);
@@ -535,15 +556,26 @@ void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...)
 
        BUG_ON(len + ret > PRINTF_BUFFER_SIZE-1);
        dev->has_error = 1;
-       if (xenbus_write(NULL, dev->nodename, "error", printf_buffer) != 0)
+
+       path_buffer = error_path(dev);
+
+       if (path_buffer == NULL) {
+               printk("xenbus: failed to write error node for %s (%s): %d\n",
+                      dev->nodename, printf_buffer, errno);
                goto fail;
+       }
 
-       kfree(printf_buffer);
-       return;
+       if (xenbus_write(NULL, path_buffer, "error", printf_buffer) != 0) {
+               printk("xenbus: failed to write error node for %s (%s)\n",
+                      dev->nodename, printf_buffer);
+               goto fail;
+       }
 
- fail:
-       printk("xenbus: failed to write error node for %s (%s)\n",
-              dev->nodename, printf_buffer);
+fail:
+       if (printf_buffer)
+               kfree(printf_buffer);
+       if (path_buffer)
+               kfree(path_buffer);
 }
 EXPORT_SYMBOL(xenbus_dev_error);
 
@@ -551,11 +583,21 @@ EXPORT_SYMBOL(xenbus_dev_error);
 void xenbus_dev_ok(struct xenbus_device *dev)
 {
        if (dev->has_error) {
-               if (xenbus_rm(NULL, dev->nodename, "error") != 0)
+               char *path_buffer = error_path(dev);
+
+               if (path_buffer == NULL) {
+                       printk("xenbus: failed to clear error node for %s: "
+                              "%d\n", dev->nodename, errno);
+                       return;
+               }
+
+               if (xenbus_rm(NULL, path_buffer, "error") != 0)
                        printk("xenbus: failed to clear error node for %s\n",
                               dev->nodename);
                else
                        dev->has_error = 0;
+
+               kfree(path_buffer);
        }
 }
 EXPORT_SYMBOL(xenbus_dev_ok);
index 105572102b7598283945ea0776ea383d2d8707fc..35eb79601a48e73a8e3f7dd4fc6fc9ff62335004 100755 (executable)
@@ -15,9 +15,13 @@ case "$ACTION" in
       vbd)
        /etc/xen/scripts/block unbind
         ;;
+      vif)
+        [ -n "$script" ] && $script down
+        ;;
     esac
     # remove device backend store entries
     xenstore-rm -t "$XENBUS_PATH"
+    xenstore-rm -t "error/$XENBUS_PATH"
     ;;
   online)
     case "$XENBUS_TYPE" in
index d8b765e5c7fee9892aed9ffb7292c5ff010c1464..201c88120c7d032781608d281bb0e47ce6fc9fd9 100644 (file)
@@ -107,7 +107,9 @@ def diagnose_devices():
                 print ("Cannot find backend path for device %s, %s." %
                        (deviceClass, device))
             else:
-                backend_error = xstransact.Read(backendPath, 'error')
+                backend_error = xstransact.Read(
+                    backendPath.replace('backend/', 'error/backend/'),
+                    'error')
 
                 if backend_error:
                     diagnose_device_error(backend_error)